using SqlSugar;
using StudyCompanion.Core.Aliyun;
using StudyCompanion.Core.Repository;
using StudyCompanion.Core.Services;
using StudyCompanion.Dto.Study;
using StudyCompanion.Entity.Study;
using StudyCompanion.Entity.User;
using StudyCompanion.IServices;
using StudyCompanion.Model.Study;

namespace StudyCompanion.Services;

/// <summary>
///     学习目录
/// </summary>
public class StudyService : BaseService, IStudyService
{
    private readonly BaseRepository<StuClassEntity> _classRepository;
    private readonly BaseRepository<UseStudyLogEntity> _useStudyLogRepository;

    public StudyService(BaseRepository<StuClassEntity> classRepository,
        BaseRepository<UseStudyLogEntity> useStudyLogRepository)
    {
        _classRepository = classRepository;
        _useStudyLogRepository = useStudyLogRepository;
    }

    /// <summary>
    ///     年级列表
    /// </summary>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<ClassListVo> ClassList()
    {
        return _classRepository.Where(x => x.IsValid == true)
            .OrderBy(x => x.Sort)
            .Select(x => new ClassListVo
            {
                Id = x.Id,
                Name = x.Name
            }).ToList();
    }

    /// <summary>
    ///     年级下学科
    /// </summary>
    /// <param name="cId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<SubjectListVo> SubjectList(long cId)
    {
        return _classRepository.Queryable<StuClassSubjectEntity, StuSubjectEntity>((t1, t2) => new object[]
            {
                JoinType.Left, t1.Subject == t2.Id && t2.IsValid == true
            })
            .Where((t1, t2) => t1.Class == cId)
            .OrderBy((t1, t2) => t1.Sort)
            .Select((t1, t2) => new SubjectListVo
            {
                Id = t1.Id,
                Name = t2.Name
            }).ToList();
    }

    /// <summary>
    ///     学科的出版社
    /// </summary>
    /// <param name="sId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<PressListVo> PressList(long sId)
    {
        return _classRepository.Queryable<StuDisciplinePressEntity, StuPressEntity>((t1, t2) => new object[]
            {
                JoinType.Left, t1.Press == t2.Id && t2.IsValid == true
            })
            .Where((t1, t2) => t1.ClassSubject == sId)
            .OrderBy((t1, t2) => t1.Sort)
            .Select((t1, t2) => new PressListVo
            {
                Id = t1.Id,
                Name = t2.Name
            }).ToList();
    }

    /// <summary>
    ///     出版社的章节
    /// </summary>
    /// <param name="pId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<SectionListVo> SectionList(long pId)
    {
        return _classRepository.Queryable<StuClassSubjectSectionEntity, StuSectionEntity>((t1, t2) => new object[]
            {
                JoinType.Left, t1.Section == t2.Id && t2.IsValid == true
            })
            .Where((t1, t2) => t1.DisciplinePress == pId)
            .OrderBy((t1, t2) => t1.Sort)
            .Select((t1, t2) => new SectionListVo
            {
                Id = t1.Id,
                Name = t2.Name,
                Describe = t1.Describe
            }).ToList();
    }

    /// <summary>
    ///     章节课程
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="sId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<CourseListVo> CourseList(long uId, long sId)
    {
        return _classRepository.Queryable<StuCourseEntity>()
            .Where(x => x.ClassSubjectSection == sId && x.IsValid == true)
            .OrderBy(x => x.Sort)
            .Select(x => new CourseListVo
            {
                Id = x.Id,
                Name = x.Name,
                HaveSeen = SqlFunc.Subqueryable<UseStudyLogEntity>()
                    .Where(y => y.Course == x.Id && y.User == uId && y.IsValid == true).Select(y => y.WatchTime),
                Duration = x.Duration
            }).ToList();
    }

    /// <summary>
    ///     课程视频
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="cId"></param>
    /// singular-point
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Tuple<StudyVideoVo, string> StudyVideo(long uId, long cId)
    {
        var useStudyLog = _useStudyLogRepository.Where(x => x.Course == cId && x.User == uId && x.IsValid == true)
            .First();
        var data = _classRepository.Queryable<StuCourseEntity, StuClassSubjectSectionEntity>((t1, t2) => new object[]
            {
                JoinType.Left, t1.ClassSubjectSection == t2.Id
            })
            .Where((t1, t2) => t1.Id == cId)
            .Select((t1, t2) => new StudyVideoVo
            {
                Id = t1.Id,
                SectionId = t2.Section,
                Name = t1.Name,
                Duration = t1.Duration,
                MediumUrl = t1.MediumUrl
            })
            .First();
        if (useStudyLog == null)
        {
            var useStudyLogInfo = new UseStudyLogEntity
            {
                User = uId,
                Course = cId,
                WatchTime = 0,
                RevampTime = DateTime.Now,
                IsValid = true
            };
            _useStudyLogRepository.Insert(useStudyLogInfo);
        }
        else
        {
            useStudyLog.RevampTime = DateTime.Now;
            _useStudyLogRepository.Update(useStudyLog);
            data.HaveSeen = useStudyLog.WatchTime;
        }

        if (data == null) return new Tuple<StudyVideoVo, string>(null, "视频资源不存在！");
        data.MediumUrl = OSS.SignUrl(data.MediumUrl, "singular-point");
        return new Tuple<StudyVideoVo, string>(data, "");
    }

    /// <summary>
    ///     播放进程记录
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public void AddPlayProcess(long uId, AddPlayProcessDto dto)
    {
        var useStudyLogInfo = _useStudyLogRepository.Where(x => x.IsValid == true)
            .Where(x => x.User == uId && x.Course == dto.cId)
            .First();
        if (useStudyLogInfo == null)
        {
            useStudyLogInfo.User = uId;
            useStudyLogInfo.Course = dto.cId;
            useStudyLogInfo.WatchTime = dto.lastTime;
            useStudyLogInfo.RevampTime = DateTime.Now;
            useStudyLogInfo.IsValid = true;
            _useStudyLogRepository.Insert(useStudyLogInfo);
        }
        else
        {
            useStudyLogInfo.WatchTime = dto.lastTime;
            _useStudyLogRepository.Update(useStudyLogInfo);
        }
    }
}